package com.wanrue.tcc.admin.dao.impl;

import com.wanrue.tcc.admin.dao.ITransactionDao;
import com.wanrue.tcc.admin.entity.Transaction;
import com.wanrue.tcc.admin.etl.DataImport;
import com.wanrue.tcc.admin.util.Page;
import com.wanrue.tcc.admin.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Repository
public class TransactionDao implements ITransactionDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    private DataImport dataImport;

    public void setDataImport(DataImport dataImport) {
        this.dataImport = dataImport;
    }

    @Override
    public List<String> getServer() {
        String sql = "SELECT DOMAIN FROM TCC_TRANSACTION GROUP BY DOMAIN";
        return jdbcTemplate.query(sql, (r, i) -> r.getString("DOMAIN"));
    }

    @Override
    public Page<Transaction> findPage(Page page) {
        String where = "";
        List array = new ArrayList();
        Map<String, Object> param = page.getParam();
        if (!StrUtil.isBlank(param.get("server"), array)) {
            where += " AND DOMAIN=?";
        }
        if (!StrUtil.isBlank(param.get("status"), array)) {
            where += " AND STATUS=?";
        }
        if (!StrUtil.isBlank(param.get("type"), array)) {
            where += " AND TYPE=?";
        }
        if (!StrUtil.isBlank(param.get("count"), array)) {
            where += " AND COUNT >=?";
        }
        if (!StrUtil.isBlank(param.get("result"), array)) {
            where += " AND RESULT=?";
        }
        List<Transaction> logList = new ArrayList<>();
        String countSql = "SELECT COUNT(1) FROM TCC_TRANSACTION WHERE 1=1 " + where;
        Integer count = jdbcTemplate.queryForObject(countSql, array.toArray(), Integer.class);
        array.add(page.getCursor());
        array.add(page.getSize());
        String listSql = "SELECT ID,GLOBAL_TX_ID, BRANCH_QUALIFIER, DOMAIN,PARTNER_STR, STATUS, TYPE, COUNT, VERSION, RESULT, CREATE_TIME, UPDATE_TIME  FROM TCC_TRANSACTION WHERE 1=1" + where + " limit ?,? ";
        if (count > 0) logList = jdbcTemplate.query(listSql, array.toArray(), new TransactionMapper());
        page.setTotal(count);
        page.setRecords(logList);
        return page;
    }

    @Override
    public int update(Transaction t) {
        int i = 0;
        if (dataImport != null) {
            i = dataImport.update(t);
            if (i == 0) return i;
            String sql = "UPDATE TCC_TRANSACTION SET STATUS=?,TYPE=?,COUNT=?,VERSION=?,RESULT=?,UPDATE_TIME=? WHERE GLOBAL_TX_ID=? and BRANCH_QUALIFIER=?";
            i = jdbcTemplate.update(sql, new Object[]{t.getStatus(), t.getType(), t.getCount(), t.getVersion() + 1, t.getResult(), new Timestamp(t.getUpdateTime().getTime()), t.getGlobalId(), t.getBranchId()});
        }
        return i;
    }

    @Override
    public void updateCache() {
        if (dataImport == null) return;
        String sql = "DELETE FROM TCC_TRANSACTION ";
        jdbcTemplate.update(sql);
        List<Transaction> data = dataImport.loadAll();
        if (data == null || data.size() == 0) return;
        sql = "INSERT INTO TCC_TRANSACTION (GLOBAL_TX_ID, BRANCH_QUALIFIER, DOMAIN, PARTNER_STR, STATUS, TYPE, COUNT, VERSION, RESULT, CREATE_TIME, UPDATE_TIME)  VALUES(?,?,?,?,?,?,?,?,?,?,?)";
        jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public int getBatchSize() {
                return data.size();
            }

            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                Transaction t = data.get(i);
                ps.setString(1, t.getGlobalId());
                ps.setString(2, t.getBranchId());
                ps.setString(3, t.getDomain());
                ps.setString(4, t.getPartner());
                ps.setInt(5, t.getStatus());
                ps.setInt(6, t.getType());
                ps.setInt(7, t.getCount());
                ps.setLong(8, t.getVersion());
                ps.setInt(9, t.getResult());
                ps.setTimestamp(10, new java.sql.Timestamp(t.getCreateTime().getTime()));
                ps.setTimestamp(11, new java.sql.Timestamp(t.getUpdateTime().getTime()));
            }
        });
    }

    @Override
    public Transaction findById(Long id) {
        String sql = "SELECT ID,GLOBAL_TX_ID, BRANCH_QUALIFIER, DOMAIN,PARTNER_STR, STATUS, TYPE, COUNT, VERSION, RESULT, CREATE_TIME, UPDATE_TIME  FROM TCC_TRANSACTION WHERE ID=?";
        List<Transaction> list = jdbcTemplate.query(sql, new Object[]{id}, new TransactionMapper());
        if (list != null && list.size() > 0) return list.get(0);
        return null;
    }

    class TransactionMapper implements RowMapper<Transaction> {
        @Override
        public Transaction mapRow(ResultSet r, int i) throws SQLException {
            Transaction transaction = new Transaction();
            transaction.setId(r.getLong("ID"));
            transaction.setGlobalId(r.getString("GLOBAL_TX_ID"));
            transaction.setBranchId(r.getString("BRANCH_QUALIFIER"));
            transaction.setDomain(r.getString("DOMAIN"));
            transaction.setPartner(r.getString("PARTNER_STR"));
            transaction.setStatus(r.getInt("STATUS"));
            transaction.setType(r.getInt("TYPE"));
            transaction.setCount(r.getInt("COUNT"));
            transaction.setVersion(r.getInt("VERSION"));
            transaction.setResult(r.getInt("RESULT"));
            transaction.setCreateTime(r.getTimestamp("CREATE_TIME"));
            transaction.setUpdateTime(r.getTimestamp("UPDATE_TIME"));
            return transaction;
        }

    }
}
